package top.xphu.zip;

import org.apache.commons.lang3.StringUtils;
import top.xphu.zip.entiy.ZFileInputStream;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * ZipUtils 不建议使用，ZipUtils结构比较乱，推荐使用 <FilePackageCore>
 * @author xphu
 * @version 1.0
 * @date 2021/6/29 14:53
 */
@Deprecated
public class ZipUtils {

    /**
     * FileOutputStream
     */
    private FileOutputStream fousa;

    /**
     * 压缩文件名称
     */
    private String zipName;

    /**
     * 创建实例对象
     * @return
     */
    public static ZipUtils instance(){
        return new ZipUtils();
    }

    /**
     * 设置压缩文件名称
     * @param zipName 压缩文件名称
     * @return ZipUtils
     */
    public ZipUtils zipName(String zipName){
        // 创建压缩文件
        if (StringUtils.isNotBlank(zipName)){
            this.zipName = (zipName.lastIndexOf('.') != -1) ? zipName : (zipName + ".zip");
        } else {
            this.zipName = "temp" + (int)(Math.random() * 100) + ".zip";
        }
        return this;
    }

    public void downloadZip(List<ZFileInputStream> zis, HttpServletResponse response) throws Exception {
        File zipFile = createZipFile(zipName);
        ZipOutputStream zos = createZipOutputStream(zipFile);
        // 将文件流写入压缩文件里面
        zipFileStream(zis, zos);
        download(zipFile, zipName, response);
    }

    public void downloadZip(HttpServletResponse response, ZFileInputStream... zis) throws Exception {
        File zipFile = createZipFile(zipName);
        ZipOutputStream zos = createZipOutputStream(zipFile);
        // 将文件流写入压缩文件里面
        zipFileStream(zos,zis);
        download(zipFile, zipName, response);
    }


    /**
     * 把全部文件打包成压缩包
     * @param files 文件集合
     * @param outputStream org.apache.tools.zip.ZipOutputStream
     */
    public void downloadZip(List<File> files, ZipOutputStream outputStream) throws Exception {
        int size = files.size();
        for (int i=0; i< size; i++){
            File file = files.get(i);
            zipFile(file, outputStream);
        }
    }

    /**
     * 创建zip文件
     * @param zipName 文件名: String
     * @return File
     * @throws IOException
     */
    public File createZipFile(String zipName) throws IOException {
        String resources = System.getProperty("user.dir") + "\\temp\\";
        File file = new File(resources);
        if (file.exists()) {
            file.mkdir();
        }
        return new File(resources +  zipName + ".zip");
    }

    /**
     *
     * @param file
     * @return
     * @throws FileNotFoundException
     */
    public InputStream getInputStream(File file) throws FileNotFoundException {
        return new FileInputStream(file);
    }

    /**
     * 创建zip文件流
     * @param file
     * @return
     * @throws IOException
     */
    private ZipOutputStream createZipOutputStream(File file) throws IOException {
        //创建文件输出流
        fousa = new FileOutputStream(file);
        return new ZipOutputStream(fousa);
    }

    /**
     * 将全部的文件流打包成压缩文件
     * @param inputStreams
     * @param outputStream
     * @throws Exception
     */
    private void zipFileStream(List<ZFileInputStream> inputStreams, ZipOutputStream outputStream) throws Exception {
        for (int i=0; i< inputStreams.size(); i++){
            ZFileInputStream zipFileInputStream = inputStreams.get(i);
            zipFile(zipFileInputStream, outputStream);
        }
        outputStream.close();
        fousa.close();
    }

    private void zipFileStream(ZipOutputStream outputStream, ZFileInputStream... inputStreams) throws Exception {
        for (int i=0; i< inputStreams.length; i++){
            ZFileInputStream zipFileInputStream = inputStreams[i];
            zipFile(zipFileInputStream, outputStream);
        }
        outputStream.close();
        fousa.close();
    }

    /**
     * 把文件打包到压缩文件中
     * @param inputFile 输入的文件
     * @param outputStream 压缩文件的输出流 org.apache.tools.zip.ZipOutputStream
     */
    private void zipFile(File inputFile, ZipOutputStream outputStream) throws Exception {
        if (inputFile == null){
            throw new Exception("输入的文件不能为空");
        }
        try{
            if (inputFile.isFile()){
                FileInputStream in = new FileInputStream(inputFile);
                BufferedInputStream bin = new BufferedInputStream(in, 1024);
                // 创建压缩文件对象
                ZipEntry zipEntry = new ZipEntry(inputFile.getName());
                outputStream.putNextEntry(zipEntry);
                // 向压缩文件中输入数据
                int i = 0;
                byte[] bytes = new byte[1024];
                while ( (i = bin.read(bytes)) != -1){
                    outputStream.write(bytes, 0, i);
                }
                // 关闭创建的流对象
                bin.close();
                in.close();
            }else {
                try{
                    File[] files = inputFile.listFiles();
                    if (files == null || files.length <= 0){
                        throw new Exception("输入的文件不能为空");
                    }
                    for (int i = 0; i < files.length; i++) {
                        zipFile(files[i], outputStream);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }

            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 把文件流打包到压缩文件中
     * @param zipFileInputStream
     * @param outputStream 压缩文件的输出流 org.apache.tools.zip.ZipOutputStream
     */
    private void zipFile(ZFileInputStream zipFileInputStream, ZipOutputStream outputStream) throws Exception {
        if (zipFileInputStream == null){
            throw new Exception("输入的文件流不能为空");
        }
        try{
            InputStream in = zipFileInputStream.getFileBody();
            if (in == null){
                throw new Exception("输入的文件流不能为空");
            }
            BufferedInputStream bin = new BufferedInputStream(in, 1024);
            // 创建压缩文件对象
            ZipEntry zipEntry = new ZipEntry(zipFileInputStream.getFileName());
            outputStream.putNextEntry(zipEntry);
            // 向压缩文件中输入数据
            int i = 0;
            byte[] bytes = new byte[1024];
            while ( (i = bin.read(bytes)) != -1){
                outputStream.write(bytes, 0, i);
            }
            // 关闭创建的流对象
            bin.close();
            in.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }


    /**
     * 下载文件
     * @param file 要下载的file文件
     * @param fileName 文件名称（不传值则使用默认的名称）
     * @param response  javax.servlet.http.HttpServletResponse
     * @return response javax.servlet.http.HttpServletResponse;
     * @throws Exception
     */
    private HttpServletResponse download(File file,String fileName, HttpServletResponse response) throws Exception {
        if (file.exists() == false){
            throw new Exception("压缩文件不存在");
        }
        if (StringUtils.isEmpty(fileName)){
            fileName = file.getName();
        }
        BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
        response.setContentType("application/x-zip-compressed");
        // 如果输出的是中文名
        response.setHeader("Content-Disposition", "attachment;filename="
                + new String(fileName.getBytes("GB2312"), "ISO8859-1"));
        // 以流的形式下载文件。
        InputStream fis = new FileInputStream(file.getPath());
        try{
            byte[] buffer = new byte[512];
            int i = 0;
            while ((i = fis.read(buffer)) != -1){
                outputStream.write(buffer, 0, i);
            }
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            try{
                File file1 = new File(file.getPath());
                if (file1.exists()){
                    file1.delete();
                }
                if (outputStream != null){
                    outputStream.flush();
                    outputStream.close();
                }
                if (fis != null){
                    fis.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return response;
    }


    /**
     * 下载文件
     * @param fis 要下载的file文件流
     * @param fileName 文件名称（不传值则使用默认的名称）
     * @param response  javax.servlet.http.HttpServletResponse
     * @return response javax.servlet.http.HttpServletResponse;
     * @throws Exception
     */
    public HttpServletResponse download(InputStream fis,String fileName, HttpServletResponse response) throws Exception {
        if (fis == null){
            throw new Exception("压缩文件不存在");
        }
        try{
            if (StringUtils.isEmpty(fileName)){
                fileName = "default.zip";
            }
            // 设置ContentType、文件名称和编码格式
            response.setContentType("application/x-zip-compressed");
            // 如果输出的是中文名
            response.setHeader("Content-Disposition", "attachment;filename="
                    + new String(fileName.getBytes("GB2312"), "ISO8859-1"));

            // 以流的形式下载文件。
            byte[] buffer = new byte[512];
            int i = 0;
            ServletOutputStream outputStream = response.getOutputStream();
//            BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
            while (( i = fis.read(buffer)) != -1){
                // 写数据关闭流
                outputStream.write(buffer, 0, i);
            }
            outputStream.flush();
            outputStream.close();
            fis.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        return response;
    }

}
